package com.easylinkin.linkappapi.device.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.easylinkin.linkappapi.annotation.CommonOperateLogAnnotate;
import com.easylinkin.linkappapi.annotation.ObjectOperationLog;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.device.constant.DeviceConstant;
import com.easylinkin.linkappapi.device.entity.Device;
import com.easylinkin.linkappapi.device.entity.DeviceModel;
import com.easylinkin.linkappapi.device.entity.vo.DeviceModelQueryVo;
import com.easylinkin.linkappapi.device.entity.vo.ElectricyStatisticsVo;
import com.easylinkin.linkappapi.device.service.DeviceService;
import com.easylinkin.linkappapi.device.vo.DeviceTypeCountVo;
import com.easylinkin.linkappapi.openapi.service.OpenApiService;
import com.easylinkin.linkappapi.operatelog.constant.LogConstant.LogModule;
import com.easylinkin.linkappapi.operatelog.constant.LogConstant.LogOperateType;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author TongJie
 * @since 2020-04-14
 */
@RestController
@Api(value = "设备控制器", tags = { "设备控制器" })
@RequestMapping("/device")
public class DeviceController {

	@Resource
	private DeviceService service;
	@Resource
	private OpenApiService openApiService;

	@ApiOperation("新增设备")
	@PostMapping("add")
	@CommonOperateLogAnnotate(module = LogModule.DEVICE, desc = "新增设备")
	@ObjectOperationLog(module = LogModule.DEVICE, desc = LogOperateType.DEVICE_ADD)
	public RestMessage add(@RequestBody @Valid Device device) {
		return RestBuilders.successBuilder(service.add(device)).build();
	}

	@ApiOperation("根据查询条件获取设备、设备空间区域名称、设备型号等数据")
	@PostMapping("get")
	public RestMessage getDevice(@RequestBody Device device) {
		Assert.notNull(device, "device 不能为空");
		device.setCodeLikeQuery(device.getCode());
		return RestBuilders.successBuilder().data(service.selectDevices(device)).build();
	}

	@ApiOperation("查询设备列表以及配电箱")
	@PostMapping("getWithElectricCheck")
	public RestMessage getWithElectricCheck(@RequestBody Device device) {
		Assert.notNull(device, "device 不能为空");
		device.setCodeLikeQuery(device.getCode());
		return RestBuilders.successBuilder().data(service.getWithElectricCheck(device)).build();
	}

	@ApiOperation("查询模块设备列表以及配电箱")
	@PostMapping("getModelDevice")
	public RestMessage getModelDevice(@RequestBody Device device) {
		Assert.notNull(device, "device 不能为空");
		return RestBuilders.successBuilder().data(service.getModelDevice(device)).build();
	}

	@ApiOperation("根据查询条件获取设备、设备空间区域名称、设备型号等数据")
	@PostMapping("getDeviceModel")
	public RestMessage getDeviceModel(@RequestBody DeviceModelQueryVo device) {
		Assert.notNull(device, "device 不能为空");
		device.setCodeLikeQuery(device.getCode());
		return RestBuilders.successBuilder().data(service.selectModelDevices(device)).build();
	}

	@ApiOperation("根据查询条件获取未关联区域的所有设备")
	@PostMapping("selectModelDeviceByArea")
	public RestMessage selectModelDeviceByArea(@RequestBody DeviceModelQueryVo device) {
		Assert.notNull(device, "device 不能为空");
		device.setCodeLikeQuery(device.getCode());
		return RestBuilders.successBuilder().data(service.selectModelDeviceByArea(device)).build();
	}

	@ApiOperation("获取不在该模块下的所有设备")
	@GetMapping({ "getNotInModel/{modelId}", "getNotInModel" })
	public RestMessage getNotInModel(@PathVariable(value = "modelId", required = false) Integer modelId) {
		// 查询这个模块下有哪些设备
		return RestBuilders.successBuilder().data(service.getNotInModel(modelId)).build();
	}

	@ApiOperation("添加对应的设备到对应的模块")
	@PostMapping("addToModel/{modelId}")
	public RestMessage addToModel(@PathVariable("modelId") Integer modelId, @RequestBody List<Device> devices) {
		// 将相关的设备添加到相关的模块中
		return RestBuilders.successBuilder().data(service.addToModel(modelId, devices)).build();
	}

	@ApiOperation("添加对应的设备到对应的模块")
	@PostMapping("removeFromModel/{modelId}")
	public RestMessage removeFromModel(@PathVariable("modelId") Integer modelId,
			@RequestBody List<DeviceModel> devices) {
		// 将相关的设备添加到相关的模块中
		return RestBuilders.successBuilder().data(service.removeFromModel(modelId, devices)).build();
	}

	@ApiOperation("修改设备模块移除状态")
	@PostMapping("/changeDeviceModelRemoveStatus/{modelId}")
	public RestMessage changeDeviceModelRemoveStatus(@PathVariable("modelId") Integer modelId,
			@RequestBody Device device) {
		return RestBuilders.successBuilder(service.changeDeviceModelRemoveStatusByModel(modelId, device)).build();
	}

	/**
	 * 设备地图页面渲染 标注设备位置所用
	 * 
	 * @param device
	 * @return
	 */
	@ApiOperation("根据查询条件获取设备位置信息list")
	@PostMapping("getDeviceSiteInfos")
	public RestMessage getDeviceSiteInfos(@RequestBody Device device) {
		Assert.notNull(device, "device 不能为空");
		return RestBuilders.successBuilder().data(service.getDeviceSiteInfos(device)).build();
	}

	@PostMapping("getDeviceSiteInfosPage")
	@ApiOperation("根据查询条件获取设备位置分页信息")
	public RestMessage getDeviceSiteInfosPage(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		IPage<Device> record = service.getDeviceSiteInfos(requestModel.getPage(), requestModel.getCustomQueryParams());
		return RestBuilders.successBuilder().data(record).build();
	}

	@ApiOperation("根据查询条件获取设备、设备空间区域名称、设备型号等分页数据")
	@PostMapping("getPage")
	public RestMessage selectPage(@RequestBody RequestModel<Device> requestModel) {
		Device customQueryParams = requestModel.getCustomQueryParams();
		Assert.notNull(customQueryParams, "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		IPage<Device> record = service.selectDevicesPage(requestModel.getPage(), customQueryParams);
		return RestBuilders.successBuilder().data(record).build();
	}

	@ApiOperation("根据查询条件获取该模块下所有设备分页数据")
	@PostMapping("getPageByModelId/{modelId}")
	public RestMessage selectPageByModelId(@RequestBody RequestModel<Device> requestModel,
			@PathVariable(name = "modelId", required = false) Integer modelId) {
		Device customQueryParams = requestModel.getCustomQueryParams();
		if (modelId != null) {
			customQueryParams.setModelId(modelId);
		}
		Assert.notNull(customQueryParams, "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		Assert.notNull(modelId, "模块id 不能为空");
		IPage<Device> record = service.selectPageByModelId(requestModel.getPage(), customQueryParams);
		return RestBuilders.successBuilder().data(record).build();
	}

	/**
	 * 空调ADC获取全量设备列表--过滤掉已绑定的设备
	 * 
	 * @param requestModel
	 * @return
	 */
	@ApiOperation("空调ADC：分页获取设备列表--过滤掉已绑定的设备")
	@PostMapping("getPageFilter")
	public RestMessage getPageFilter(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		IPage<Device> record = service.selectDevicesPageFilter(requestModel.getPage(),
				requestModel.getCustomQueryParams());
		return RestBuilders.successBuilder().data(record).build();
	}

	@ApiOperation("空调ADC：获取全量设备列表--过滤掉已绑定的设备")
	@PostMapping("getAllFilter")
	public RestMessage getAllFilter(@RequestBody Device device) {
		Assert.notNull(device, "device 不能为空");
		return RestBuilders.successBuilder().data(service.selectDevicesPageFilter(device)).build();
	}

	@ApiOperation("空调ADC-获取设备及绑定关系")
	@PostMapping("getPageFilterDifferBind")
	public RestMessage getPageFilterDifferBind(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		IPage<Device> record = service.selectDevicesFilterDifferBind(requestModel.getPage(),
				requestModel.getCustomQueryParams());
		return RestBuilders.successBuilder().data(record).build();
	}

	@PostMapping("getMonitorPage")
	@ApiOperation("设备监控页-查询设备")
	public RestMessage getMonitorPage(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		IPage<Device> record = service.getMonitorPage(requestModel.getPage(), requestModel.getCustomQueryParams());
		return RestBuilders.successBuilder().data(record).build();
	}

	@PostMapping("getDistributionMonitorDevices")
	@ApiOperation("电力监控设备监控页-查询设备")
	public RestMessage getDistributionMonitorDevices(@RequestParam("distributionRoomId") String distributionRoomId) {
		return RestBuilders.successBuilder().data(service.getDistributionMonitorDevices(distributionRoomId)).build();
	}

	@PostMapping("selectDevicesWithAlarmRule")
	@ApiOperation("查询设备,与规则关联或无关联")
	public RestMessage selectDevicesWithAlarmRule(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "customQueryParams 不能为空");
		Assert.notNull(requestModel.getPage(), "page 不能为空");
		IPage<Device> record = service.selectDevicesWithAlarmRule(requestModel.getPage(),
				requestModel.getCustomQueryParams());
		return RestBuilders.successBuilder().data(record).build();
	}

	@ApiOperation("修改设备")
	@PostMapping("update")
	@ObjectOperationLog(module = LogModule.DEVICE, desc = LogOperateType.DEVICE_UPDATE)
	@CommonOperateLogAnnotate(module = LogModule.DEVICE, desc = "修改设备")
	public RestMessage update(@RequestBody Device device) {
		try {
			openApiService.updateDeviceInstall(device);
		} catch (Exception e) {
			throw new RuntimeException("保存到linkthing报错," + e.toString());
		}
		return RestBuilders.successBuilder(service.update(device)).build();
	}

	@ApiOperation("批量删除设备")
	@PostMapping("deleteBatch")
	@CommonOperateLogAnnotate(module = LogModule.DEVICE, desc = "批量删除设备")
	@ObjectOperationLog(module = LogModule.DEVICE, desc = LogOperateType.DEVICE_DELETE)
	public RestMessage deleteBatch(@RequestBody List<Device> deviceList) {
		Assert.notEmpty(deviceList, "参数为空");
		return RestBuilders.successBuilder(service.deleteBatch(deviceList)).build();
	}

	@ApiOperation("批量强删除设备")
	@PostMapping("deleteBatchForce")
	@CommonOperateLogAnnotate(module = LogModule.DEVICE, desc = "批量强删除设备")
	@ObjectOperationLog(module = LogModule.DEVICE, desc = LogOperateType.DEVICE_DELETE)
	public RestMessage deleteBatchForce(@RequestBody List<Device> deviceList) {
		Assert.notEmpty(deviceList, "参数为空");
		service.deleteBatchForce(deviceList);
		return RestBuilders.successBuilder().build();
	}

	/**
	 * 根据设备ids 查询被资产用到的 资产ids
	 */
	@ApiOperation("根据设备ids 查询被资产用到的 资产ids")
	@PostMapping("selectAssetIdsByIds")
	public RestMessage selectAssetIdsByIds(@RequestBody List<String> ids) {
		return RestBuilders.successBuilder(service.selectAssetIdsByIds(ids)).build();
	}

	@GetMapping("getImportTemplate")
	@ApiOperation("下载导入模板")
	public void getImportTemplate(HttpServletRequest request, HttpServletResponse response) {
		service.getImportTemplate(request, response);
	}

	@PostMapping("exportData")
	@ApiOperation("设备导出")
	public void exportData(@RequestBody Device device, HttpServletRequest request, HttpServletResponse response) {
		service.exportData(device, request, response);
	}

	@ApiOperation("导入设备")
	@PostMapping("importData")
	@CommonOperateLogAnnotate(module = LogModule.DEVICE, desc = "导入设备", recordParam = false)
	public RestMessage importData(@RequestParam(value = "file") MultipartFile file, Device device) {
		Assert.notNull(file, "文件不能为空");
		Assert.notNull(device, "设备参数为空");
		Set errors = service.importData(file, device);
		if (errors.isEmpty()) {
			return RestBuilders.successBuilder().data("导入成功").build();
		} else {
			String errorMsg = "";
			for (Object obj : errors) {
				errorMsg = errorMsg + "第" + obj.toString() + "行  ";
			}
			errorMsg = errorMsg + "数据错误,请核对后再提交。";
			return RestBuilders.successBuilder().data(errorMsg).build();
		}
	}

	@GetMapping("getImportTemplateSpace")
	@ApiOperation("下载导入模板")
	public void getImportTemplateSpace(HttpServletRequest request, HttpServletResponse response) {
		service.getImportTemplateSpace(request, response);
	}

	@ApiOperation("设备绑定空间")
	@PostMapping("deviceBindArea")
	@CommonOperateLogAnnotate(module = LogModule.DEVICE, desc = "设备绑定空间", recordParam = false)
	public RestMessage deviceBindArea(@RequestParam(value = "file") MultipartFile file) {
		Assert.notNull(file, "文件不能为空");
		service.deviceBindArea(file);
		return RestBuilders.successBuilder().data("导入成功").build();
	}

	@ApiOperation("根据设备类型名称统计设备数量")
	@PostMapping("/getStatisticsByType")
	public RestMessage getStatisticsByType(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		return RestBuilders.successBuilder().data(service.getStatisticsByType(device)).build();
	}

	@ApiOperation("根据设备类型名称统计设备数量,筛选出设备数量大于0的数据")
	@PostMapping("/getStatisticsExistDeviceByType")
	public RestMessage getStatisticsExistDeviceByType(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		return RestBuilders.successBuilder().data(service.getStatisticsExistDeviceByType(device)).build();
	}

	// 铁路设备类型统计
	@PostMapping("/rail/getStatisticsExistDeviceByType")
	public RestMessage railGetStatisticsExistDeviceByType(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		List<DeviceTypeCountVo> statisticsExistDeviceByType = service.getStatisticsExistDeviceByType(device);
		// deviceTypeName 对应 RailwayDeviceType.description
		List<DeviceTypeCountVo> result = new ArrayList<>();
		Map<String, DeviceTypeCountVo> map = statisticsExistDeviceByType.stream().collect(Collectors
				.toMap(DeviceTypeCountVo::getDeviceTypeName, Function
						.identity(), (k1, k2) -> k1));
		for (DeviceConstant.RailwayDeviceType value : DeviceConstant.RailwayDeviceType.values()) {
			if(map.containsKey(value.getDescription())) {
				DeviceTypeCountVo deviceTypeCountVo = map.get(value.getDescription());
				deviceTypeCountVo.setDeviceTypeId(value.getType().toString());
				result.add(deviceTypeCountVo);
			}else{
				DeviceTypeCountVo deviceTypeCountVo = new DeviceTypeCountVo();
				deviceTypeCountVo.setDeviceTypeId(value.getType().toString());
				deviceTypeCountVo.setDeviceTypeName(value.getDescription());
				deviceTypeCountVo.setDeviceCount(0);
				result.add(deviceTypeCountVo);
			}
		}
		return RestBuilders.successBuilder().data(result).build();
	}


	/**
	 * 设备状态统计
	 * 
	 * @param device
	 * @return
	 */
	@ApiOperation("设备状态统计（正常 / 告警）")
	@PostMapping("/countDeviceByStatus")
	public RestMessage countDeviceByStatus(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		return RestBuilders.successBuilder().data(service.countDeviceByStatus(device)).build();
	}

	@ApiOperation("设备在线离线统计（在线 / 离线）")
	@PostMapping("/countDeviceByOnlineState")
	public RestMessage countDeviceByOnlineState(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		return RestBuilders.successBuilder().data(service.countDeviceByOnlineState(device)).build();
	}

	@ApiOperation("统计一定时间段内新增的设备数量,并按天进行分组")
	@PostMapping("/getStatisticsDeviceCount")
	public RestMessage getStatisticsDeviceCount(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "参数为空");
		Assert.notNull(requestModel.getPage(), "page参数为空");
		return RestBuilders.successBuilder()
				.data(service.getStatisticsDeviceCount(requestModel.getPage(), requestModel.getCustomQueryParams()))
				.build();
	}

	/**
	 * 统计时间区间之前的(每天、每月)时间纬度条件内的设备新增数量，以及设备增量趋势 返回数据示例： 时间 每天新增 增量累计 createTime
	 * oneDayAddCount addUpCount 2021-11-10 150 10712 2021-11-08 2 10562 2021-11-04
	 * 2 10560 2021-11-02 8 10558 2021-11-01 6 10550
	 * 
	 * @param requestModel
	 * @return
	 */
	@ApiOperation("统计时间区间之前的(每天、每月)时间纬度条件内的设备新增数量，以及设备增量趋势")
	@PostMapping("/getStatisticsDeviceAddUpCount")
	public RestMessage getStatisticsDeviceAddUpCount(@RequestBody RequestModel<Device> requestModel) {
		Assert.notNull(requestModel.getCustomQueryParams(), "参数为空");
		Assert.notNull(requestModel.getPage(), "page参数为空");
		return RestBuilders.successBuilder().data(
				service.getStatisticsDeviceAddUpCount(requestModel.getPage(), requestModel.getCustomQueryParams()))
				.build();
	}

	@ApiOperation("设备新增数量统计保存至device_info表中")
	@PostMapping("/getDeviceStatisticsAuditTask")
	public RestMessage getDeviceStatisticsAuditTask(@RequestBody Device device) {
		service.getDeviceStatisticsAuditTask(device);
		return RestBuilders.successBuilder().build();
	}

	/**
	 * 和getStatisticsDeviceAddUpCount此接口一样，看查询条件怎么用吧。 接口名称取的不是很符合
	 * 
	 * @param device
	 * @return
	 */
	@ApiOperation("统计时间区间之前的(每天、每月)时间纬度条件内的设备新增数量，以及设备增量趋势")
	@PostMapping("/getStatisticsDeviceOnlineOffLine")
	public RestMessage getStatisticsDeviceOnlineOffLine(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		return RestBuilders.successBuilder().data(service.getStatisticsDeviceOnlineOffLine(device)).build();
	}

	/**
	 * 增强版，缺少数据可继续扩展，如需要继续对数据筛选，可在业务层进行过滤 根据条件按设备型号进行分组获取设备总数、正常数、离线数、告警数
	 */
	@ApiOperation("根据条件按设备型号进行分组获取设备总数、正常数、离线数、告警数")
	@PostMapping("/getDeviceCountByUnitCode")
	public RestMessage getDeviceCountByUnitCode(@RequestBody Device device) {
		Assert.notNull(device, "参数为空");
		return RestBuilders.successBuilder().data(service.getDeviceCountByUnitCode(device)).build();
	}

	/**
	 * 删除重复的设备属性状态表
	 */
	@PostMapping("/deleteRepeatedDeviceAttrStatus")
	public RestMessage deleteRepeatedDeviceAttrStatus() {
		return RestBuilders.successBuilder().data(service.deleteRepeatedDeviceAttrStatus()).build();
	}

	/**
	 * 获取相机列表
	 */
	@GetMapping("/getAiCameraList")
	public RestMessage getAiCameraList() {
		return RestBuilders.successBuilder().data(service.getAiCameraList()).build();
	}

	/**
	 * 获取相机列表
	 */
	@PostMapping("/getDeviceList")
	public RestMessage getDeviceList(@RequestBody Device device) {
		return RestBuilders.successBuilder().data(service.selectDevicesList(device)).build();
	}

	@ApiOperation("根据查询条件获取设备、设备空间区域名称、设备型号等分页数据")
	@PostMapping("/selectByTypeNameList")
	public RestMessage selectByTypeNameList(@RequestBody Device device) {
		Assert.notNull(device, "customQueryParams 不能为空");
		if (StringUtils.isEmpty(device.getDeviceTypeName())){
           return RestBuilders.failureMessage("设备类型不能为空");
		}
		List<Device> record = service.selectByTypeNameDevicesList(device);
		return RestBuilders.successBuilder().data(record).build();
	}


}
